﻿////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// <copyright>Copyright 2008-2011 Andreas Huber Doenni</copyright>
// Distributed under the Microsoft Public License (Ms-PL).
// See accompanying file License.txt or copy at http://mews.codeplex.com/license.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

namespace Mews.Net.Nntp.Cache
{
    using System;
    using System.Data.SqlServerCe;

    /// <summary>Provides the means to update groups fast.</summary>
    internal sealed class GroupUpdater : IDisposable
    {
        private static readonly string[] displayNameColumn = { GroupNames.DisplayNameColumn };
        private static readonly string[] newInboundArticlesReceiveLimitColumn =
        {
            GroupNames.NewInboundArticlesReceiveLimitColumn
        };

        private static readonly string[] cachedInboundArticlesLimitColumn =
        {
            GroupNames.CachedInboundArticlesLimitColumn
        };

        private static readonly string[] selectedInboundArticleNumberColumn =
        {
            GroupNames.SelectedInboundArticleNumberColumn
        };

        private static readonly string[] inboundArticleFilterColumns =
        {
            GroupNames.IsOriginalInboundArticleBeingWatchedFilterColumn,
            GroupNames.HasOriginalInboundArticleBeenReadFilterColumn,
            GroupNames.IsFollowupInboundArticleBeingWatchedFilterColumn,
            GroupNames.HasFollowupInboundArticleBeenReadFilterColumn
        };

        private readonly SqlCeCommand command;
        private readonly SqlCeResultSet resultSet;

        private readonly int groupNameMaxLength;
        private readonly int groupDisplayNameMaxLength;

        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        /// <summary>See <see cref="IDisposable.Dispose"/>.</summary>
        public void Dispose()
        {
            this.resultSet.Dispose();
            this.command.Dispose();
        }

        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        internal GroupUpdater(SqlCeConnection connection)
        {
            using (var groupCommandGuard =
                ScopeGuard.Create(this.command = CommandHelper.Create(connection, GroupNames.Table)))
            using (var groupResultSetGuard =
                ScopeGuard.Create(this.resultSet = this.command.ExecuteResultSet(ResultSetOptions.Updatable)))
            {
                using (var groupSchemaTable = this.resultSet.GetSchemaTable())
                {
                    this.groupNameMaxLength = SqlCeHelper.GetColumnSize(groupSchemaTable, GroupNames.NameColumn);
                    this.groupDisplayNameMaxLength =
                        SqlCeHelper.GetColumnSize(groupSchemaTable, GroupNames.DisplayNameColumn);
                }

                groupCommandGuard.Dismiss();
                groupResultSetGuard.Dismiss();
            }
        }

        internal int GroupNameMaxLength
        {
            get { return this.groupNameMaxLength; }
        }

        internal int GroupDisplayNameMaxLength
        {
            get { return this.groupDisplayNameMaxLength; }
        }

        internal void UpdateDisplayName(int groupId, string displayName)
        {
            this.Update(groupId, displayNameColumn, displayName);
        }

        internal void UpdateNewInboundArticlesReceiveLimit(int groupId, int newInboundArticlesReceiveLimit)
        {
            this.Update(groupId, newInboundArticlesReceiveLimitColumn, newInboundArticlesReceiveLimit);
        }

        internal void UpdateCachedInboundArticlesLimit(int groupId, int cachedInboundArticlesLimit)
        {
            this.Update(groupId, cachedInboundArticlesLimitColumn, cachedInboundArticlesLimit);
        }

        internal void UpdateInboundArticleFilter(int groupId, InboundArticleFilter articleFilter)
        {
            this.Update(
                groupId,
                inboundArticleFilterColumns,
                articleFilter.IsOriginalBeingWatched,
                articleFilter.HasOriginalBeenRead,
                articleFilter.IsFollowupBeingWatched,
                articleFilter.HasFollowupBeenRead);
        }

        internal void UpdateSelectedInboundArticleNumber(int groupId, long? selectedInboundArticleNumber)
        {
            this.Update(groupId, selectedInboundArticleNumberColumn, selectedInboundArticleNumber);
        }

        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        private void Update(int groupId, string[] columnNames, params object[] values)
        {
            this.resultSet.Update(new object[] { groupId }, columnNames, values);
        }
    }
}
